import { useAuth } from "context/auth-context";
import qs from "qs";
import * as auth from "../auth-provider";

const apiUrl = process.env.REACT_APP_API_URL;

/**
 * RequestInit 是 fetch() 的入参，这里自定义 Config 类型是为了扩展字段
 */
interface Config extends RequestInit {
  token?: string; // 令牌
  data?: object; // 请求数据
}

/**
 * fetch 封装
 * @param endpoint 请求地址
 * @param config 请求配置
 * @returns
 */
export const http = async (
  endpoint: string,
  { data, token, headers, ...customConfig }: Config = {}
) => {
  const config = {
    method: "GET",
    headers: {
      Authorization: token ? `Bearer ${token}` : "",
      "Content-Type": data ? "application/json" : "",
    },
    ...customConfig, // 这些参数可以覆盖上面的参数，比如修改请求方式为 POST
  };

  // 对于 GET 请求要把请求数据转换为 querystring 拼接在请求地址后
  if (config.method.toUpperCase() === "GET") {
    endpoint += `?${qs.stringify(data)}`;
  } else {
    // 对于非 GET 请求要把请求数据转换为 json
    config.body = JSON.stringify(data || {});
  }

  return window
    .fetch(`${apiUrl}/${endpoint}`, config)
    .then(async (response) => {
      if (response.status === 401) {
        // 服务端返回 401 表示不在登录状态
        await auth.logout();
        window.location.reload();
        return Promise.reject({ message: "请重新登录" });
      }
      const data = await response.json();
      if (response.ok) {
        return data;
      } else {
        // 响应异常需要手动抛出异常，否则 catch() 捕获不了异常。
        return Promise.reject(data);
      }
    });
};

export const useHttp = () => {
  const { user } = useAuth();
  // TODO
  return (...[endpoint, config]: Parameters<typeof http>) =>
    http(endpoint, { ...config, token: user?.token });
};
